export default class PosterDesignTool {
	data = {};
	drawing = true;
	toImagetask = [];
	nickName = '';
	qrcodeUrl = '';
	userId = '';
	avatarUrl = '';

	constructor(canvasContext, componentInstance, canvasId) {
		this.ctx = canvasContext;
		this.componentInstance = componentInstance;
		this.canvasId = canvasId;
	}

	setData(data) {
		this.data = data;
	}

	setQrcodeUrl(url) {
		if (Object.keys(this.data).length === 0) return console.warn('请先设置data，或者一次性填充data后调用draw')
		this.qrcodeUrl = url;
	}

	setUserNickName(nickName) {
		if (Object.keys(this.data).length === 0) return console.warn('请先设置data，或者一次性填充data后调用draw')
		this.nickName = nickName
	}

	setUserId(id) {
		if (Object.keys(this.data).length === 0) return console.warn('请先设置data，或者一次性填充data后调用draw')
		this.userId = id;
	}

	setUserAvatar(url) {
		if (Object.keys(this.data).length === 0) return console.warn('请先设置data，或者一次性填充data后调用draw')
		this.avatarUrl = url;
	}

	async draw(callBack) {
		this.drawing = true;
		this.ctx.clearRect(0, 0, this.data.width, this.data.height);
		//填充背景颜色
		this.ctx.setFillStyle(this.data.backgroundColor)
		this.ctx.fillRect(0, 0, this.data.width, this.data.height);

		for (let i = 0, length = this.data.body.length; i < length; i++) {
			const widget = this.data.body[i];
			if (widget.type === 3) {
				if (this.avatarUrl) widget.src = this.avatarUrl;
			} else if (widget.type === 4) {
				if (this.nickName) widget.value = this.nickName;
			} else if (widget.type === 5) {
				if (this.userId) widget.value = this.userId;
			} else if (widget.type === 6) {
				if (this.qrcodeUrl) widget.src = this.qrcodeUrl;
			}
			this.ctx.save();
			this.ctx.beginPath();
			if (widget.type === 0 || widget.type === 2 || widget.type === 3 || widget.type === 6) { //绘制图像
				await this.drawImageWidget(widget)
			} else if (widget.type === 1 || widget.type === 4 || widget.type === 5) { //绘制文本
				this.drawTextWidget(widget)
			}
			this.ctx.closePath();
			this.ctx.restore();
		}


		this.ctx.draw(false, () => {
			this.drawing = false;
			if (this.toImagetask.length > 0) {
				this.toImage().then(res => {
					this.toImagetask.forEach(({ resolve }) => {
						resolve(res)
					})
				}).catch(() => {
					this.toImagetask.forEach(({ reject }) => {
						reject(false)
					})
				})
			}
			callBack && callBack();
		});

	}

	//绘制图像
	drawImageWidget(widget) {
		return new Promise(async resolve => {
			const ctx = this.ctx;
			let { src, width, height, x, y, borderRadius } = widget;
			if (borderRadius == undefined) borderRadius = 0;
			borderRadius = Math.min((Math.min(width, height) / 2), borderRadius)

			let img;

			try {
				//检查是否存在跨域
				let imageNode = await this.loadImg(
					src,
					// "https://erpbaoku.oss-cn-chengdu.aliyuncs.com/erp/tenant/goodsImg/fb6892eba4bd099615877bc12db711fa.jpg" //测试图片
				);
				img = imageNode.src;
			} catch (e) {
				return uni.showToast({
					title: `图片加载失败，可能存在跨域。`,
					icon: 'none'
				})
			}

			//绘制图片圆角
			ctx.arc(x + borderRadius, y + borderRadius, borderRadius, Math.PI, (Math.PI * 3) / 2);
			ctx.lineTo(width - borderRadius + x, y);
			ctx.arc(width - borderRadius + x, borderRadius + y, borderRadius, (Math.PI * 3) / 2, Math
			.PI * 2);
			ctx.lineTo(width + x, height + y - borderRadius);
			ctx.arc(width - borderRadius + x, height - borderRadius + y, borderRadius, 0, (Math.PI *
				1) / 2);
			ctx.lineTo(borderRadius + x, height + y);
			ctx.arc(borderRadius + x, height - borderRadius + y, borderRadius, (Math.PI * 1) / 2, Math
			.PI);
			ctx.closePath();
			ctx.clip();

			ctx.drawImage(img, x, y, width, height);
			resolve()
		})
	}

	//绘制文本
	drawTextWidget(widget) {
		const ctx = this.ctx;
		let {
			color,
			fontSize,
			width,
			// height,
			x,
			y,
			letterSpacing,
			lineHeight,
			// textAlign,
			textFotmat,
			value,
			maxLine
		} =
		widget;

		//em to px
		lineHeight = fontSize * lineHeight
		y += lineHeight; //修正位置，因为文字是从y坐标绘制底部

		ctx.setFillStyle(color);
		ctx.setStrokeStyle(color);

		// 多个连续空格只保留一个
		let tempText = (value.replace(/(^\s*)|(\s*$)/g, ' ').replace(/ +/g, ' ')).trim();
		let textLen = tempText.length

		this.ctx.font =
			`${textFotmat.includes("italic")?"italic" +" ":""}${textFotmat.includes("bold")?"bold":"normal"} ${fontSize}px YaHei`

		let strArray = []
		let tempStr = ''
		for (let i = 0; i < textLen; i++) {
			let currStr = tempText[i]
			// 判断当前字符是否是换行符，如果是，那么新增下一行
			let isWrap = !/\r?\n/.test(currStr)
			if (
				isWrap &&
				(
					this.ctx.measureText(tempStr + currStr).width +
					(tempStr.length + 1) * letterSpacing
				) < width
			) {
				// 如果不是换行符且当前绘制的文本宽度加字距小于最大宽度，直接当前行字符串直接拼接
				tempStr += currStr
			} else {
				// 否则就是当前行的宽度已经达到极限，进行换行
				strArray.push(tempStr)
				if (isWrap) {
					// 如果不是换行符，直接新的一行开头就是这个字符
					tempStr = currStr
				} else {
					// 否则，新的一行开头将换行符替换为空字符串
					tempStr = ''
				}
			}
		}

		// 如果还有剩余结尾的字符串，直接就算作一行
		if (tempStr != '') {
			strArray.push(tempStr)
			tempStr = ''
		}

		const haveMaxLine = maxLine !== undefined;
		if (haveMaxLine) {
			strArray = strArray.slice(0, maxLine)
		}
		strArray.forEach((str, index) => {
			// 逐行绘制，绘制的 y 坐标当前行行数加上字体大小加上行高近似的模拟
			this.handleDrawOneLineText(str, x, y, index * lineHeight, letterSpacing, textFotmat
			.includes("line-through"), fontSize, haveMaxLine && index === strArray.length - 1 &&
			strArray.length >= maxLine)
		})
	}

	handleDrawOneLineText(str, startLeft, startTop, y, letterSpacing, lineThrough, fontSize, isLastLine) {
		let tempStr = ''
		for (let i = 0, len = str.length; i < len; i++) {
			// 逐字绘制，每行的y不变，单个字符的x是前面绘制文本的宽度加上每个字符的间距和
			this.ctx.fillText(
				(isLastLine && i === len - 1) ? '...' : str[i],
				startLeft + i * letterSpacing + (this.ctx.measureText(tempStr).width),
				startTop + y
			)
			tempStr += str[i]
		}


		if (lineThrough) {
			//绘制完毕当前行，绘制中划线
			this.ctx.setLineWidth(Math.max(1, fontSize / 9.33))
			const exceed = 6

			const middleY = startTop + y - fontSize / 3
			this.ctx.moveTo(startLeft - exceed / 2, middleY)
			this.ctx.lineTo(startLeft + this.ctx.measureText(tempStr).width + letterSpacing * (tempStr.length - 1) +
				exceed / 2, middleY)
			this.ctx.stroke()
		}
	}

	//生成图片
	toImage() {
		return new Promise((resolve, reject) => {
			if (this.drawing) {
				this.toImagetask.push({ resolve, reject })
			} else {
				const that = this;
				uni.canvasToTempFilePath({
					destWidth: that.data.width * 2, //放大一倍图片更清晰
					destHeight: that.data.height * 2, //放大一倍图片更清晰
					height: that.data.height,
					canvasId: that.canvasId,
					success: res => {
						resolve(res.tempFilePath)
					},
					fail: (err) => {
						uni.showToast({
							title: '生成失败',
							icon: 'none'
						});
						reject(false);
					}
				}, that.componentInstance);
			}
		})
	}

	loadImg(url) {
		return new Promise((resolve, reject) => {
			let img = new Image();
			img.setAttribute('crossOrigin', 'anonymous');
			img.src = url + '?t=' + new Date().getTime();
			img.onload = function() {
				resolve(img);
			}
			img.onerror = function(err) {
				reject(err);
			}
		});
	}
}